#include <iostream>
#include <vector>
using namespace std;

inline bool reachable(int v){return v!=0;}
// the two parts of the bipartite graph is A, B; this must be the most useful version
// G_type[a][b] means there is a edge from a to b, or defined with reachable(v)
typedef vector<vector<int> > G_type;
inline int nLeft(const G_type& g){return g.size();}
inline int nRight(const G_type& g){return g[0].size();}
bool augment(const G_type& g, vector<int>& used, vector<int>& link, int t)
{
	int right_num=nRight(g);
	for(int i=0;i<right_num;i++)
	{
		if(!used[i]&&reachable(g[t][i]))
		{
			used[i]=1;
			if(link[i]==-1||augment(g, used, link,link[i]))
			{
				link[i]=t;
				return true;
			}
		}
	}
	return false;
}
int bipartite_match3(const G_type& g, vector<int>& used, vector<int>& link)
{
	int left_num=nLeft(g) , right_num=nRight(g);
	link.assign(right_num, -1);
	used.resize(right_num);
	// go
	int num=0;
	for(int i=0;i<left_num;i++)
	{
		fill(used.begin(), used.end(), 0);
		if(augment(g, used, link,i))
			num++;
	}
	return num;
}

int main()
{
	return 0;
}
